<!-- 画布 -->
<template>
	<div
		:key="cpnWrapperId"
		class="parent"
		@drop.prevent.stop="dragComDown"
		@dragover.prevent
		:style="canvasStyle"
		@click="handleClickOutside">
		<VueDraggableResizable
			v-for="item in screenCpnsState.screenCpns"
			class="drag-item"
			:class="{ activeCpn: screenCpnsState.activeCpnId === item.id }"
			v-bind="{
				key: item.id,
				w: item.canvas.wh.w,
				h: item.canvas.wh.h,
				x: item.canvas.xy.x,
				y: item.canvas.xy.y,
				z: item.canvas.z,
				scale: sketchRuleState.canvasOpts.canvasSacle,
				parent: true,
				'class-name-handle': 'my-handle-class',
			}"
			@contextmenu.prevent="($event) => onContextMenu($event, item)"
			@dragging="(...args) => onDragging(...args, item)"
			@resizing="(...args) => onResizing(...args, item)"
			@drag-stop="(...args) => onDragEnd(...args, item)"
			@activated="activated(item)">
			<RenderCpn :cpnInfo="item"></RenderCpn>
			<context-menu
				v-if="screenCpnsState.activeCpnId === item.id"
				v-model:show="showContext"
				:options="optionsComponent">
				<context-menu-item
					v-for="item in ['删除']"
					:label="item"
					@click="handleRClickBtn(item)" />
			</context-menu>
		</VueDraggableResizable>
		<!-- 辅助线 -->
		<template v-if="standardLineOpts.visible">
			<StandardLine w :w-line="standardLineOpts.wLine"></StandardLine>
			<StandardLine :h-line="standardLineOpts.hLine"></StandardLine>
		</template>
	</div>
</template>
<script setup>
import RenderCpn from "@/views/LowCode/components/RenderCpn/RenderCpn.vue";
import StandardLine from "./components/StandardLine/StandardLine.vue";
import { ref, reactive, computed, toRefs } from "vue";
import { guid } from "@/utils";
import { useSketchRuleStore } from "@/stores/sketchRule";
import { useScreenCpnsStore } from "@/stores/screenCpns";
import { storeToRefs } from "pinia";
const sketchRuleStore = useSketchRuleStore();
const ScreenCpnsStore = useScreenCpnsStore();
const { sketchRuleState } = storeToRefs(sketchRuleStore);
const { screenCpnsState } = storeToRefs(ScreenCpnsStore);
const props = defineProps({
	dragCpn: {
		// 拖拽进入的组件
		type: Object,
		default: () => {},
	},
});
// 大屏(canvas)的宽高发生变化重新渲染
const cpnWrapperId = computed(() => {
	return (
		sketchRuleState.value.id +
		sketchRuleState.value.rulerOpts.canvasHeight +
		sketchRuleState.value.rulerOpts.canvasWidth
	);
});
// 记录活跃的组件
const activeCpnId = ref(-1);
// 画布配置
const canvasStyle = computed(() => {
	return {
		position: "relative", // 让辅助线以parent作为父元素
		background: sketchRuleState.value.canvasOpts.canvasBgColor,
		width: `${sketchRuleState.value.rulerOpts.canvasWidth}px`,
		height: `${sketchRuleState.value.rulerOpts.canvasHeight}px`,
	};
});
// 辅助线配置
const standardLineOpts = reactive({
	visible: false,
	wLine: 0,
	hLine: 0,
});
// 展示showContext
const showContext = ref(false);
// context-menu 配置
const optionsComponent = reactive({
	x: 1,
	y: 1,
});
// 当前聚焦组件
const activated = (cpn) => {
	screenCpnsState.value.activeCpnId = cpn.id;
};
// 拖动事件(记录组件坐标, 辅助线赋值)
const onDragging = (x, y, cpn) => {
	standardLineOpts.visible = true;
	standardLineOpts.wLine = y;
	standardLineOpts.hLine = x;
	(cpn.canvas.xy.x = x), (cpn.canvas.xy.y = y);
};
// 缩放事件(记录组件宽高)
const onResizing = (x, y, w, h, cpn) => {
	cpn.canvas.wh.w = w;
	cpn.canvas.wh.h = h;
};
// 组件拖动结束时触发
const onDragEnd = (left, top, vm) => {
	standardLineOpts.visible = false;
};
// 如果是高亮元素则不会取消高亮状态，如果不是则取消高亮状态
const handleClickOutside = (event) => {
	// 获取被点击的元素
	const clickedElement = event.target.className;
	if (clickedElement === "parent") {
		screenCpnsState.value.activeCpnId = null;
	}
};
// 左侧面板拖拽进入画布时触发的回调函数
const dragComDown = (e) => {
	const { clientX, clientY } = e;
	const { dragCpn } = toRefs(props);
	dragCpn.value.canvas.xy.x = clientX;
	dragCpn.value.canvas.xy.y = clientY;
	// 当前拖拽进入画布的组件
	const currentDragCom = {
		id: guid(),
		...dragCpn.value,
	};
	screenCpnsState.value.activeCpnId = currentDragCom.id;
	screenCpnsState.value.screenCpns.push(currentDragCom);
};
// 右键菜单打开事件
const onContextMenu = (e, cpn) => {
	const { id } = cpn;
	const { clientX, clientY } = e;
	e.preventDefault();
	screenCpnsState.value.activeCpnId = id;
	showContext.value = true;
	optionsComponent.x = clientX;
	optionsComponent.y = clientY;
};
const handleRClickBtn = (t) => {
	switch (t) {
		case "删除":
			screenCpnsState.value.screenCpns = screenCpnsState.value.screenCpns.filter(
				(item) => item.id != screenCpnsState.value.activeCpnId
			);
			screenCpnsState.value.activeCpnId = null;
			break;
	}
};
</script>
<style lang="scss">
.parent {
	box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1), 0 10px 25px rgba(0, 0, 0, 0.1);
	border-radius: 10px; /* 可选，添加圆角更美观 */
	.drag-item {
		position: absolute;
		border: 1px dashed #333333;
		box-sizing: border-box;
	}
}
.activeCpn {
	border-color: #0089d0;
	cursor: move;

	.my-handle-class {
		width: 20px;
		height: 20px;
		position: absolute;
		box-sizing: border-box;
		border: 5px solid #f5f129;
	}
}
// 每个句柄不同样式
.my-handle-class-tl {
	top: -2px !important;
	left: -2px !important;
	display: block !important;
	cursor: nw-resize;
	border-right: none !important;
	border-bottom: none !important;
}

.my-handle-class-tm {
	top: -2px !important;
	left: calc(50% - 8px) !important;
	display: block !important;
	cursor: n-resize;
	border-left: none !important;
	border-right: none !important;
	border-bottom: none !important;
}

.my-handle-class-tr {
	top: -2px !important;
	right: -2px !important;
	display: block !important;
	cursor: ne-resize;
	border-left: none !important;
	border-bottom: none !important;
}

.my-handle-class-mr {
	top: calc(50% - 8px) !important;
	right: -2px !important;
	display: block !important;
	cursor: e-resize;
	border-left: none !important;
	border-top: none !important;
	border-bottom: none !important;
}

.my-handle-class-br {
	right: -2px !important;
	bottom: -2px !important;
	display: block !important;
	cursor: se-resize;
	border-left: none !important;
	border-top: none !important;
}

.my-handle-class-bm {
	right: calc(50% - 8px) !important;
	bottom: -2px !important;
	display: block !important;
	cursor: s-resize;
	border-left: none !important;
	border-right: none !important;
	border-top: none !important;
}

.my-handle-class-bl {
	left: -2px !important;
	bottom: -2px !important;
	display: block !important;
	cursor: sw-resize;
	border-right: none !important;
	border-top: none !important;
}

.my-handle-class-ml {
	top: calc(50% - 8px) !important;
	left: -2px !important;
	display: block !important;
	cursor: w-resize;
	border-top: none !important;
	border-right: none !important;
	border-bottom: none !important;
}
</style>
